﻿namespace XUCore.Webs
{
    /********************************************************************
*           Copyright:       2009-2011
*           Company:
*           CRL Version :    4.0.30319.239
*           Created by 徐毅 at 2011/11/29 12:46:54
*                   mailto:3624091@qq.com
*
********************************************************************/

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using XUCore.Extensions;
    using XUCore.Serializer;

    /// <summary>
    /// Url构造器
    /// </summary>
    public class UrlBuilder
    {
        private IDictionary<string, object>
                _parameters = new SortedDictionary<string, object>();

        private string _host;
        private string _requestUrl;
        private bool _isCompleteParameter = true;

        /// <summary>
        /// 客户端名（自定义标识）
        /// </summary>
        /// <value></value>
        public string ClientName { get; set; }
        /// <summary>
        /// 请求地址
        /// </summary>
        /// <value></value>
        public string Url { get; private set; }
        /// <summary>
        /// 参数列表
        /// </summary>
        public IDictionary<string, object> Parameters => _parameters;
        /// <summary>
        /// Form Url Encode
        /// </summary>
        public FormUrlEncodedContent FormUrlEncodedContent
        {
            get
            {
                return new FormUrlEncodedContent(_parameters.Select(m => new KeyValuePair<string, string>(m.Key, m.Value.SafeString())));
            }
        }
        /// <summary>
        /// multipart/form-data
        /// </summary>
        public MultipartFormDataContent MultipartFormDataContent { get; set; }
        /// <summary>
        /// 参数字符串
        /// </summary>
        public string ParameterString
        {
            get
            {
                return _parameters.Select(m => m.Key + "=" + m.Value).DefaultIfEmpty().Aggregate((m, n) => m + "&" + n);
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public UrlBuilder()
        {
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="requestUrl">请求url</param>
        public UrlBuilder(string requestUrl)
        {
            _requestUrl = requestUrl;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="clientName">请求名</param>
        /// <param name="requestUrl">请求地址</param>
        public UrlBuilder(string clientName, string requestUrl)
        {
            _requestUrl = requestUrl;
            ClientName = clientName;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="requestUrl">请求地址</param>
        /// <param name="keyValues">请求参数</param>
        public UrlBuilder(string requestUrl, params KeyValuePair<string, object>[] keyValues)
        {
            _requestUrl = requestUrl;
            foreach (var item in keyValues)
                this.Add(item.Key, item.Value);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="clientName">请求名</param>
        /// <param name="requestUrl">请求参数</param>
        /// <param name="keyValues">请求参数</param>
        public UrlBuilder(string clientName, string requestUrl, params KeyValuePair<string, object>[] keyValues)
        {
            _requestUrl = requestUrl;
            ClientName = clientName;
            foreach (var item in keyValues)
            {
                this.Add(item.Key, item.Value);
            }
        }
        /// <summary>
        /// 创建一个新的构造器
        /// </summary>
        /// <returns></returns>
        public static UrlBuilder Create() => new UrlBuilder();
        /// <summary>
        /// 创建一个新的构造器，完整URL = Host + RequestUrl
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <returns></returns>
        public static UrlBuilder Create(string requestUrl) => new UrlBuilder(string.Empty, requestUrl);
        /// <summary>
        /// 创建一个新的构造器，完整URL = clientName + RequestUrl，clientName为启动注册的http对象key标识
        /// </summary>
        /// <param name="clientName"></param>
        /// <param name="requestUrl"></param>
        /// <returns></returns>
        public static UrlBuilder Create(string clientName, string requestUrl) => new UrlBuilder(clientName, requestUrl);
        /// <summary>
        /// 是否合并参数 true：生成url的时候追加参数，false：构造HttpContent（FormUrlEncodedContent 或者 JsonContent）
        /// </summary>
        /// <param name="completeParameter">是否合并参数，true：生成url的时候追加参数，false：不追加</param>
        /// <returns></returns>
        public UrlBuilder SetParameter(bool completeParameter)
        {
            _isCompleteParameter = completeParameter;
            return this;
        }
        /// <summary>
        /// 追加合并url后缀的参数 a=1&amp;b=2&amp;c=3
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public UrlBuilder SetUrlParameter(Func<UrlBuilder, UrlBuilder> parameter)
        {
            _isCompleteParameter = true;

            parameter.Invoke(this);

            return this;
        }
        /// <summary>
        /// 构造HttpContent（FormUrlEncodedContent 或者 JsonContent）
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public UrlBuilder SetContentParameter(Func<UrlBuilder, UrlBuilder> parameter)
        {
            _isCompleteParameter = false;

            parameter.Invoke(this);

            return this;
        }
        /// <summary>
        /// 构造HttpContent（MultipartFormDataContent）用户http 上传文件请求，含多文件
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public UrlBuilder SetFormDataContent(Func<UrlMultipartFormDataContent, UrlMultipartFormDataContent> form)
        {
            var mult = form.Invoke(UrlMultipartFormDataContent.Create());

            MultipartFormDataContent = mult.MultipartFormDataContent;

            return this;
        }
        /// <summary>
        /// 写入请求名，完整URL = clientName + RequestUrl，clientName为启动注册的http对象key标识
        /// </summary>
        /// <param name="clientName"></param>
        /// <returns></returns>
        public UrlBuilder SetClientName(string clientName)
        {
            ClientName = clientName;
            return this;
        }
        /// <summary>
        /// 写入Host，完整URL = Host + RequestUrl
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public UrlBuilder SetHost(string host)
        {
            _host = host;
            return this;
        }
        /// <summary>
        /// 写入requestUrl，完整URL = Host + RequestUrl
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <returns></returns>
        public UrlBuilder SetRequestUrl(string requestUrl)
        {
            _requestUrl = requestUrl;
            return this;
        }
        /// <summary>
        /// 添加参数
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public UrlBuilder Add(string key, object value)
        {
            if (!_parameters.ContainsKey(key))
                _parameters.Add(key, value);
            else
                _parameters[key] = value;

            return this;
        }
        /// <summary>
        /// 添加参数
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public UrlBuilder Add(bool condition, string key, object value)
        {
            if (!condition)
                return this;

            if (!_parameters.ContainsKey(key))
                _parameters.Add(key, value);
            else
                _parameters[key] = value;

            return this;
        }
        /// <summary>
        /// 删除参数
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public UrlBuilder Remove(string key)
        {
            if (_parameters != null && _parameters.ContainsKey(key))
                _parameters.Remove(key);

            return this;
        }
        /// <summary>
        /// 清空Url
        /// </summary>
        /// <returns></returns>
        public UrlBuilder Clear()
        {
            _parameters.Clear();
            _host = string.Empty;
            _requestUrl = string.Empty;
            return this;
        }
        /// <summary>
        /// 完成构造，生成最终请求Url
        /// </summary>
        /// <returns></returns>
        public UrlBuilder Complete()
        {
            var url = new StringBuilder();
            url.Append(_host);
            url.Append(_requestUrl);

            if (_isCompleteParameter)
            {
                if (_parameters.Count == 0)
                {
                    Url = url.ToString();
                    return this;
                }
                if (!_requestUrl.EndsWith("&"))
                    url.Append("?");

                url.Append(ParameterString);
            }

            Url = url.ToString();
            return this;
        }
        /// <summary>
        /// 输出HttpContent（FormUrlEncoded）
        /// </summary>
        /// <param name="formUrlEncodedContent"></param>
        /// <returns></returns>
        public UrlBuilder Out(out FormUrlEncodedContent formUrlEncodedContent)
        {
            formUrlEncodedContent = FormUrlEncodedContent;

            return this;
        }
        /// <summary>
        /// 输出HttpContent（Json Body）
        /// </summary>
        /// <param name="jsonContent"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public UrlBuilder Out(out HttpContent jsonContent, Encoding encoding)
        {
            jsonContent = new StringContent(Parameters.ToJson(), encoding ?? Encoding.UTF8, "application/json");

            jsonContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            return this;
        }
        /// <summary>
        /// 输出HttpContent（MultipartFormDataContent）
        /// </summary>
        /// <param name="multipartFormDataContent"></param>
        /// <returns></returns>
        public UrlBuilder Out(out MultipartFormDataContent multipartFormDataContent)
        {
            multipartFormDataContent = MultipartFormDataContent;

            return this;
        }

        /// <summary>
        /// 输出请求和参数
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="parameters"></param>
        /// <param name="paramString"></param>
        /// <returns></returns>
        public UrlBuilder Out(out string requestUrl, out IDictionary<string, object> parameters, out string paramString)
        {
            requestUrl = $"{_host}{_requestUrl}";
            parameters = Parameters;
            paramString = ParameterString;

            return this;
        }

        /// <summary>
        /// ToString
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.Complete().Url;
        }
    }
}